<!DOCTYPE html>
<html>
<head>
  <title>Test - Observability</title>
  <link rel="stylesheet" href="../QUnit.css" type="text/css" />
  <script type="text/javascript" src="../QUnit.js"></script>
  <script type="text/javascript" src="../QUnitExt.js"></script>
</head>
<body>
  <h1 id="qunit-header">Test Results</h1>
  <h2 id="qunit-banner"></h2>
  <h2 id="qunit-userAgent"></h2>
  <ol id="qunit-tests"></ol>
  <br />
  <textarea id="qunit-log" rows="10" cols="100"></textarea>
  <script type="text/javascript" src="../Scripts/Sharpen.debug.js"></script>
  <script type="text/javascript">
  function Binding(src, prop) {
    this.src = src;
    this.prop = prop;
    this.invalidateCount = 0;
  }
  var Binding$proto = {
    invalidateObserver: function() {
      this.invalidateCount++;
    },
    updateTarget: function() {
      var reg = ss.Observable.registerObserver(this);
      this.value = this.src['get_' + this.prop]();
      reg.dispose();
    },
    updateSource: function(v) {
      this.src['set_' + this.prop](v);
    }
  };

  function Model() {
    this._name = new ss.Observable();
  }
  var Model$proto = {
    get_name: function() {
      return this._name.getValue();
    },
    set_name: function(v) {
      this._name.setValue(v);
    }
  };
  
  var Test = ss.ns('Test');
  ss.type(Test,
    [ Binding, 'Binding', Binding$proto ],
    [ Model, 'Model', Model$proto ]);


  module('Observability');
  test('observable', function() {
    var num = new ss.Observable(10);

    QUnit.equal(num.getValue(), 10);
    num.setValue(100);

    QUnit.equal(num.getValue(), 100);
  });

  test('singleObserver', function() {
    var model = new Model();
    model.set_name('Foo');
    
    var binding = new Binding(model, 'name');
    
    binding.updateTarget();
    QUnit.equal(binding.value, 'Foo');
    QUnit.equal(binding.invalidateCount, 0);

    binding.updateSource('Bar');
    binding.updateTarget();
    QUnit.equal(binding.value, 'Bar');
    QUnit.equal(binding.invalidateCount, 1);

    binding.updateSource('Bar');
    binding.updateTarget();
    QUnit.equal(binding.value, 'Bar');
    QUnit.equal(binding.invalidateCount, 1);

    binding.updateSource('Baz');
    binding.updateTarget();
    QUnit.equal(binding.value, 'Baz');
    QUnit.equal(binding.invalidateCount, 2);
  });

  test('multipleObservers', function() {
    var model = new Model();
    model.set_name('Foo');
    
    var binding = new Binding(model, 'name');
    var binding2 = new Binding(model, 'name');
    
    binding.updateTarget();
    binding2.updateTarget();
    QUnit.equal(binding.value, 'Foo');
    QUnit.equal(binding.invalidateCount, 0);
    QUnit.equal(binding2.invalidateCount, 0);

    binding.updateSource('Bar');
    binding.updateTarget();
    binding2.updateTarget();
    QUnit.equal(binding.value, 'Bar');
    QUnit.equal(binding.invalidateCount, 1);
    QUnit.equal(binding2.invalidateCount, 1);

    binding.updateSource('Bar');
    binding.updateTarget();
    binding2.updateTarget();
    QUnit.equal(binding.value, 'Bar');
    QUnit.equal(binding.invalidateCount, 1);
    QUnit.equal(binding2.invalidateCount, 1);

    model.set_name('Baz');
    binding.updateTarget();
    binding2.updateTarget();
    QUnit.equal(binding2.value, 'Baz');
    QUnit.equal(binding.invalidateCount, 2);
    QUnit.equal(binding2.invalidateCount, 2);
  });

  test('observableCollection', function() {
    var items = new ss.ObservableCollection();
    var binding = new Binding(items, 'length');
    
    binding.updateTarget();
    QUnit.equal(binding.value, 0);
    QUnit.equal(binding.invalidateCount, 0);
    
    items.add('abc');
    QUnit.equal(binding.invalidateCount, 1);
    
    items.add('def');
    QUnit.equal(binding.invalidateCount, 1);

    binding.updateTarget();
    items.removeAt(1);
    QUnit.equal(binding.invalidateCount, 2);
  });

  test('unobservedAccessPreservesExistingObservers', function() {
    var model = new Model();
    model.set_name('Foo');
    
    var binding = new Binding(model, 'name');
    binding.updateTarget();

    QUnit.equal(binding.value, 'Foo');
    QUnit.equal(binding.invalidateCount, 0);

    var s = model.get_name();

    model.set_name('Bar');
    binding.updateTarget();
    QUnit.equal(binding.invalidateCount, 1);
    QUnit.equal(binding.value, 'Bar');
  });
  </script>
</body>

</html>
